/*
 * \file TraitListModel.cpp
 *
 * \date Jan 9, 2009
 * \author Sarah Smith <sez@storybridge.org>
 */

#include "TraitListModel.h"

#include <DndData/Trait.h>
#include <DndData/Feat.h>
#include <DndData/Power.h>

#include <Xml/XmlDirectory.h>
#include <Xml/XmlPath.h>

#include <QIcon>
#include <QSettings>
#include <QStringList>
#include <QDir>

/*!
 * \class TraitListModel
 * \brief Template class providing a Qt Model for complex data items.
 * \details The model constructed is intended for use in a QListView and displays
 * the entries by title and description.  Checkboxes displayed allow the user to
 * select a number of the items.
 * \sa DataListModel
 */

/*!
 * \brief Construct a new TraitListModel.
 * \details The model is of type \a T, and contains data items found on the \a path.
 * \tparam T a Trait, Race or other item implementing the TitledData interface.
 * \param path Path to list items from.
 * \param icon to assign to every item in the list.
 * \param parent for this object to be linked to.
 */
template <typename T>
TraitListModel<T>::TraitListModel(const XmlPath &path, QIcon icon, QObject *parent)
    : QStandardItemModel(parent)
{
    QDir typeDir = path.dir();
    QStringList names = typeDir.entryList(QDir::Files, QDir::Name);
    QStringList::const_iterator it = names.begin();
    for ( ; it != names.end(); ++it)
    {
        QList<QStandardItem*> row;
        QStandardItem *item = new QStandardItem(*it);
        item->setCheckable(true);
        item->setIcon(icon);
        row << item;
        T t(*it);
        t.loadFromXml();
        mData << t;
        item = new QStandardItem(t.description());
        row << item;
        appendRow(row);
    }
}

/*!
 * \brief Destroy this TraitListModel.
 * \details Typical empty Qt destructor.
 */
template <typename T>
TraitListModel<T>::~TraitListModel()
{
}

/*!
 * \brief Retrieve a list of all items of type \a T checked.
 * \details After the user has selected several items by checking in the
 * associated view, use this method to obtain the checked items as a QList.
 * \tparam typename of the model, and of the QList returned.
 * \return QList of the selected items.
 */
template <typename T>
QList<T> TraitListModel<T>::selected() const
{
    int rows = rowCount();
    QList<T> result;
    for (int i = 0; i < rows; ++i)
    {
        if (item(i)->checkState() == Qt::Checked)
            result << mData[i];
    }
    return result;
}

/*!
 * \brief Set the items of type \a T to appear as checked.
 * \details When editing an existing item with some list of data
 * attached, use this method to set the checked items in the view to those
 * in the existing item.
 * \tparam typename of the model, and of the QList being set.
 * \param data QList<T> of data to set as checked.
 */
template <typename T>
void TraitListModel<T>::setSelected(QList<T> data)
{
    for (int i = 0; i < mData.size(); ++i)
    {
        if (data.contains(mData.at(i)))
            item(i)->setCheckState(Qt::Checked);
        else
            item(i)->setCheckState(Qt::Unchecked);
    }
}

/*!
 * \brief Add the data item to the model.
 * \details When editing an item, add a new entry to the list of
 * data items attached, by calling add() with \a data.
 * \tparam typename of the model, and of the data item added.
 * \param data item to add.
 */
template <typename T>
void TraitListModel<T>::add(T data)
{
    mData << data;
    QList<QStandardItem*> row;
    QStandardItem *entry = new QStandardItem(data.title());
    entry->setCheckable(true);
    entry->setIcon(item(0, 0)->icon());
    row << entry;
    entry = new QStandardItem(data.description());
    row << entry;
    appendRow(row);
}

template class TraitListModel<Trait>;
template class TraitListModel<Power>;
template class TraitListModel<Feat>;

/*!
 * \brief Convenience factory method to construct a TraitModel.
 * \details Construct and return a TraitModel from the \a path
 * as a base, and "Trait" as sub-type.  An appropriate icon is used.
 * \param QString className type name, eg "Race/Dwarf" for a
 * Dwarven Racial Trait.
 */
TraitModel *makeTraitModel(const XmlPath &path, QObject *parent)
{
    XmlPath xPath = path;
    xPath.setSubType(XmlPath::TRAIT_TYPE);
    return new TraitModel(xPath,
            QIcon(":/icons/icons/16x16/actions/edit-clear.png"),
            parent);
}

/*!
 * \brief Convenience factory method to construct a PowerModel.
 * \details Construct and return a PowerModel from the \a path
 * as a base, and "Power" as sub-type.  An appropriate icon is used.
 * \param QString className type name, eg "Class/Cleric" for a
 * Cleric Class Power.
 */
PowerModel *makePowerModel(const XmlPath &path, QObject *parent)
{
    XmlPath xPath = path;
    xPath.setSubType(XmlPath::POWER_TYPE);
    return new PowerModel(xPath,
            QIcon(":/icons/icons/16x16/actions/view-fullscreen.png"),
            parent);
}

/*!
 * \brief Convenience factory method to construct a FeatModel.
 * \details Construct and return a FeatModel, using "Feat" as the base
 * and an appropriate icon.
 */
FeatModel *makeFeatModel(QObject *parent)
{
    return new FeatModel(XmlPath(XmlPath::FEAT_BASE),
            QIcon(":/icons/icons/16x16/actions/mail-mark-junk.png"),
            parent);
}

/*!
 * \brief Convenience factory method to construct a RaceModel.
 * \details Construct and return a RaceModel, using "Race" as the base
 * and an appropriate icon.
 */
RaceModel *makeRaceModel(QObject *parent)
{
    return new RaceModel(XmlPath(XmlPath::RACIAL_BASE),
            QIcon(":/icons/icons/16x16/actions/contact-new.png"),
            parent);
}
